package org.budo.filestore.local;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.util.Arrays;

import org.budo.filestore.api.DeleteResponse;
import org.budo.filestore.api.DownloadRequest;
import org.budo.filestore.api.UploadRequest;
import org.budo.filestore.api.UploadResponse;
import org.budo.filestore.impl.DefaultDeleteResponse;
import org.budo.filestore.impl.DefaultUploadResponse;
import org.budo.support.java.io.util.FileLastModifiedComparator;
import org.budo.support.lang.util.FileUtil;
import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author lmw
 */
public class LocalFileStore extends AbstractLocalFileStore {
    private static final Logger log = LoggerFactory.getLogger(LocalFileStore.class);

    public LocalFileStore() {
    }

    public LocalFileStore(String rootPath) {
        this.setRootPath(rootPath);
    }

    /**
     * @see #downloadStream(DownloadRequest)
     */
    @Override
    public String downloadUrl(DownloadRequest request) {
        if (StringUtil.isEmpty(this.getDownloadUrlPrefix())) {
            return this.getRootPath() + (this.getRootPath().endsWith("/") ? "" : "/") + request.getContentUrl();
        }

        return this.getDownloadUrlPrefix() + (this.getDownloadUrlPrefix().endsWith("/") ? "" : "/") + request.getContentUrl();
    }

    @Override
    public UploadResponse upload(UploadRequest request) {
        File fileTo = new File(this.rootPath(), request.getContentUrl());
        FileUtil.createNewFile(fileTo);

        IoUtil.write(request.getInputStream(), IoUtil.fileOutputStream(fileTo));

        // 如果文件过多就删除
        this.deleteFileIfTooMany();

        return new DefaultUploadResponse(true);
    }

    private void deleteFileIfTooMany() {
        if (this.getMaxFileCount() < 0) {
            return;
        }

        File[] files = new File(this.getRootPath()).listFiles();
        int fileCount = files.length;

        int toDeleteCount = fileCount - this.getMaxFileCount();
        if (toDeleteCount <= 0) {
            return;
        }

        Arrays.sort(files, FileLastModifiedComparator.ASC);
        for (int i = 0; i < toDeleteCount; i++) {
            files[i].delete();
        }
    }

    @Override
    public InputStream downloadStream(DownloadRequest request) {
        File fileFrom = new File(this.rootPath(), request.getContentUrl());
        if (!fileFrom.exists()) {
            log.debug("#46 downloadStream return null, request={}", request);
            return null;
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        IoUtil.write(IoUtil.fileInputStream(fileFrom), outputStream);
        return new ByteArrayInputStream(outputStream.toByteArray());
    }

    @Override
    public DeleteResponse delete(DownloadRequest request) {
        File file = new File(this.rootPath(), request.getContentUrl());
        boolean success = file.delete();
        return new DefaultDeleteResponse(success);
    }
}